package cn.xieyang.gen.obsidian;

import cn.hutool.core.io.FileUtil;
import cn.hutool.core.io.LineHandler;

import java.io.File;
import java.nio.charset.StandardCharsets;
import java.nio.file.Path;
import java.util.*;
import java.util.concurrent.*;
import java.util.stream.Collectors;

public class MoveAttach {


    private static Map<String, String> attachMap = new HashMap<>();

    private static Set<String> dirSet = new HashSet<>();

    private static int count = 200;

    public static void main(String[] args) throws ExecutionException, InterruptedException {
        System.out.println("开始");
        long start = System.currentTimeMillis();
        String attachDir = "D:\\code\\per\\x-ob-blog\\attach\\webPage\\attach";
        Arrays.stream(FileUtil.ls(attachDir)).forEach(file -> {
            if (!file.isDirectory()) {
                String fileName = file.getName();
                String path = file.getAbsoluteFile().toPath().toString();
                attachMap.put(fileName, path);
            }
        });
        String noteDir = "D:\\code\\per\\x-ob-blog";
        Arrays.stream(FileUtil.ls(noteDir)).forEach(file -> {
            if (file.isDirectory()) {
                scanNodeDir(file);
            }
        });
        List<FutureTask> list = new ArrayList<>();
        ExecutorService executorService = Executors.newFixedThreadPool(20);
        CopyOnWriteArrayList<File> files = new CopyOnWriteArrayList<>();
        searchFile(files, noteDir, executorService, list);
        if (!files.isEmpty()) {
            searchFilesAndMoveAttach(files);
        }
        for (FutureTask task : list) {
            task.get();
        }
        System.out.println("耗时：" + (System.currentTimeMillis() - start) / 1000 + "s");
        System.out.println("结束");
    }

    private static void searchFile(CopyOnWriteArrayList<File> files, String noteDir, ExecutorService executorService, List<FutureTask> list) {
        Arrays.stream(FileUtil.ls(noteDir)).forEach(file -> {
            if (file.isDirectory() && !file.getName().startsWith(".")) {
                searchFile(files, file.getAbsolutePath(), executorService, list);
            }
            files.add(file);
            if (list.size() >= count) {
                FutureTask<String> futureTask = new FutureTask<>(() -> {
                    List<File> tmp = new ArrayList<>(files);
                    files.clear();
                    return searchFilesAndMoveAttach(tmp);
                });
                executorService.execute(futureTask);
                list.add(futureTask);
            }
        });
    }

    private static String searchFilesAndMoveAttach(List<File> fileList) {
        fileList.stream().forEach(file -> {
            if (file.isFile()) {
                FileUtil.readLines(file, StandardCharsets.UTF_8, (LineHandler) line -> {
                    List<String> collect = attachMap.keySet().stream().filter(key -> line.contains(key)).collect(Collectors.toList());
                    if (!collect.isEmpty()) {
                        String absolutePath = file.getParentFile().getAbsolutePath();
                        absolutePath += "/attach";
                        if (!FileUtil.exist(absolutePath)) {
                            FileUtil.mkdir(absolutePath);
                        }
                        String sourcePath = attachMap.get(collect.get(0));
                        String targetPath = absolutePath + "\\" + collect.get(0);
                        try {
                            FileUtil.move(new File(sourcePath).toPath(), Path.of(targetPath), false);
                            System.out.println(Thread.currentThread().getName() + "移动文件：" + sourcePath + " -> " + targetPath);
                        } catch (Exception e) {
                            System.out.println(Thread.currentThread().getName() + "移动文件失败：" + sourcePath + " -> " + targetPath);
                        }

                    }
                });
            }
        });
        return "";
    }

    private static void scanNodeDir(File dirFile) {
        Arrays.asList(FileUtil.ls(dirFile.getAbsolutePath())).stream().forEach(file -> {
            if (file.isDirectory()) {
                scanNodeDir(file);
            }
            if (isNodeDir(dirFile)) {
                dirSet.add(dirFile.getName());
            }
        });
    }


    private static boolean isNodeDir(File dirFile) {
        if (dirFile.isDirectory()) {
            List<File> collect = Arrays.asList(FileUtil.ls(dirFile.getAbsolutePath())).stream().filter(file -> {
                if (file.isFile()) {
                    String name = file.getName().split("[.]")[0];
                    return name.equals(dirFile.getName());
                } else {
                    return false;
                }
            }).collect(Collectors.toList());
            return !collect.isEmpty();
        }
        return false;
    }


}
